package com.dzsw.mybatisx.gen.util;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.FileType;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Map;

/**
 * @author sunz
 * @version 1.0
 * @CreateTime 2021-05-14-10:16
 */
public class MyFreemarkerEngine extends AbstractTemplateEngine {

  private Configuration configuration;

  @Override
  public MyFreemarkerEngine init(ConfigBuilder configBuilder) {
    super.init(configBuilder);
    configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    configuration.setDefaultEncoding(ConstVal.UTF8);
    configuration.setClassForTemplateLoading(FreemarkerTemplateEngine.class, StringPool.SLASH);
    return this;
  }


  @Override
  public void writer(Map<String, Object> objectMap, String templatePath, String outputFile)
      throws Exception {
//    if (outputFile.contains("xml")) {
//      outputFile = outputFile.replaceFirst("xml", "");
//    }
    objectMap.put("mtc", new MyTypeConvert());
    objectMap.put("myHelper", new MyHelper());
    Template template = configuration.getTemplate(templatePath);
    try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
      template.process(objectMap, new OutputStreamWriter(fileOutputStream, ConstVal.UTF8));
    }
    logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
  }

  private void writerFile(Map<String, Object> objectMap, String templatePath, String outputFile)
      throws Exception {
    this.writer(objectMap, templatePath, outputFile);
  }


  @Override
  public String templateFilePath(String filePath) {
    return filePath + ".ftl";
  }

  @Override
  public AbstractTemplateEngine batchOutput() {
    try {
      List<TableInfo> tableInfoList = getConfigBuilder().getTableInfoList();
      for (TableInfo tableInfo : tableInfoList) {
        Map<String, Object> objectMap = getObjectMap(tableInfo);
        Map<String, String> pathInfo = getConfigBuilder().getPathInfo();
        TemplateConfig template = getConfigBuilder().getTemplate();
        // 自定义内容
        InjectionConfig injectionConfig = getConfigBuilder().getInjectionConfig();
        if (null != injectionConfig) {
          injectionConfig.initTableMap(tableInfo);
          objectMap.put("cfg", injectionConfig.getMap());
          List<FileOutConfig> focList = injectionConfig.getFileOutConfigList();
          if (CollectionUtils.isNotEmpty(focList)) {
            for (FileOutConfig foc : focList) {
              if (isCreate(FileType.OTHER, foc.outputFile(tableInfo))) {
                writerFile(objectMap, foc.getTemplatePath(), foc.outputFile(tableInfo));
              }
            }
          }
        }
        // Mp.java
        String entityName = tableInfo.getEntityName();
        if (null != entityName && null != pathInfo.get(ConstVal.ENTITY_PATH)) {
          String entityFile = String.format(
              (pathInfo.get(ConstVal.ENTITY_PATH) + File.separator + "%s" + suffixJavaOrKt()),
              entityName);
          if (isCreate(FileType.ENTITY, entityFile)) {
            writerFile(objectMap, templateFilePath(
                template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
          }
        }
        // MpMapper.java
        if (null != tableInfo.getMapperName() && null != pathInfo.get(ConstVal.MAPPER_PATH)) {
          String mapperFile = String.format(
              (pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName()
                  + suffixJavaOrKt()), entityName);
          if (isCreate(FileType.MAPPER, mapperFile)) {
            writerFile(objectMap, templateFilePath(template.getMapper()), mapperFile);
          }
        }
        // MpMapper.xml
        if (null != tableInfo.getXmlName() && null != pathInfo.get(ConstVal.XML_PATH)) {
          String xmlFile = String.format(
              (pathInfo.get(ConstVal.XML_PATH) + File.separator + tableInfo.getXmlName()
                  + ConstVal.XML_SUFFIX), entityName);
          if (isCreate(FileType.XML, xmlFile)) {
            writerFile(objectMap, templateFilePath(template.getXml()), xmlFile);
          }
        }
        // IMpService.java
        if (null != tableInfo.getServiceName() && null != pathInfo.get(ConstVal.SERVICE_PATH)) {
          String serviceFile = String.format(
              (pathInfo.get(ConstVal.SERVICE_PATH) + File.separator + tableInfo.getServiceName()
                  + suffixJavaOrKt()), entityName);
          if (isCreate(FileType.SERVICE, serviceFile)) {
            writerFile(objectMap, templateFilePath(template.getService()), serviceFile);
          }
        }
        // MpServiceImpl.java
        if (null != tableInfo.getServiceImplName() && null != pathInfo
            .get(ConstVal.SERVICE_IMPL_PATH)) {
          String implFile = String.format(
              (pathInfo.get(ConstVal.SERVICE_IMPL_PATH) + File.separator + tableInfo
                  .getServiceImplName() + suffixJavaOrKt()), entityName);
          if (isCreate(FileType.SERVICE_IMPL, implFile)) {
            writerFile(objectMap, templateFilePath(template.getServiceImpl()), implFile);
          }
        }
        // MpController.java
        if (null != tableInfo.getControllerName() && null != pathInfo
            .get(ConstVal.CONTROLLER_PATH)) {
          String controllerFile = String.format(
              (pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo
                  .getControllerName() + suffixJavaOrKt()), entityName);
          if (isCreate(FileType.CONTROLLER, controllerFile)) {
            writerFile(objectMap, templateFilePath(template.getController()), controllerFile);
          }
        }
        // view
        String viewName = tableInfo.getEntityName() + "VO";
        if (null != viewName && null != pathInfo.get(ConstVal.ENTITY_PATH)) {
          String viewFile = String.format(
              (pathInfo.get(ConstVal.ENTITY_PATH) + File.separator + "%s" + suffixJavaOrKt()),
              viewName);
          if (isCreate(FileType.OTHER, viewFile)) {
            writerFile(objectMap, templateFilePath("templates/view.java"), viewFile);
          }
        }
        // showDoc
        String showDocName = tableInfo.getComment();
        if (null != showDocName && null != pathInfo.get(ConstVal.ENTITY_PATH)) {
          String showDocFile = String.format(
                  (pathInfo.get(ConstVal.ENTITY_PATH) + File.separator + "%s.sql"),
                  showDocName);
//          List<TableField> list = tableInfo.getFields();
//          for (TableField tf : list) {
//            System.out.println(JsonUtil.toJson(tf));
//          }
          if (isCreate(FileType.OTHER, showDocFile)) {
            writerFile(objectMap, templateFilePath("templates/show_doc.sql"), showDocFile);
          }
        }
      }
    } catch (Exception e) {
      logger.error("无法创建文件，请检查配置信息！", e);
    }
    return this;
  }
}
